package com.ai.imagetext.service;

import com.ai.imagetext.dto.ImageDTO;
import com.ai.imagetext.entity.Image;
import com.ai.imagetext.entity.ImageTag;
import com.ai.imagetext.entity.Tag;
import com.ai.imagetext.repository.GeneratedImageRepository;
import com.ai.imagetext.repository.ImageRepository;
import com.ai.imagetext.repository.ImageTagRepository;
import com.ai.imagetext.repository.TagRepository;
import com.ai.imagetext.repository.TextContentRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Slf4j
@Service
@RequiredArgsConstructor
public class ImageService {

    private final ImageRepository imageRepository;
    private final TagRepository tagRepository;
    private final ImageTagRepository imageTagRepository;
    private final TextContentRepository textContentRepository;
    private final GeneratedImageRepository generatedImageRepository;

    /**
     * 获取所有图片（分页）
     */
    public Page<ImageDTO> getAllImages(int page, int size, String sortBy, String sortDir) {
        log.info("Getting all images: page={}, size={}, sortBy={}, sortDir={}", page, size, sortBy, sortDir);

        Sort sort = Sort.by(Sort.Direction.fromString(sortDir), sortBy);
        Pageable pageable = PageRequest.of(page, size, sort);

        Page<Image> imagePage = imageRepository.findByIsDeletedFalse(pageable);
        return imagePage.map(this::convertToDTO);
    }

    /**
     * 根据ID获取图片
     */
    public Optional<ImageDTO> getImageById(Long id) {
        log.info("Getting image by ID: {}", id);

        Optional<Image> image = imageRepository.findByIdAndIsDeletedFalse(id);
        return image.map(this::convertToDTO);
    }

    /**
     * 根据关键词搜索图片
     */
    public Page<ImageDTO> searchImages(String keyword, int page, int size, String sortBy, String sortDir) {
        log.info("Searching images with keyword: {}", keyword);

        Sort sort = Sort.by(Sort.Direction.fromString(sortDir), sortBy);
        Pageable pageable = PageRequest.of(page, size, sort);

        Page<Image> imagePage = imageRepository.findByKeyword(keyword, pageable);
        return imagePage.map(this::convertToDTO);
    }

    /**
     * 根据标签筛选图片
     */
    public List<ImageDTO> getImagesByTag(String tagName) {
        log.info("Getting images by tag: {}", tagName);

        List<Long> imageIds = imageTagRepository.findImageIdsByTagName(tagName);
        List<Image> images = imageRepository.findAllById(imageIds)
                .stream()
                .filter(image -> !image.getIsDeleted())
                .collect(Collectors.toList());

        return images.stream().map(this::convertToDTO).collect(Collectors.toList());
    }

    /**
     * 根据多个标签筛选图片（AND逻辑）
     */
    public List<ImageDTO> getImagesByTags(List<String> tagNames) {
        log.info("Getting images by tags: {}", tagNames);

        if (tagNames == null || tagNames.isEmpty()) {
            return List.of();
        }

        // 获取第一个标签的图片
        List<Long> imageIds = imageTagRepository.findImageIdsByTagName(tagNames.get(0));

        // 对于其他标签，取交集
        for (int i = 1; i < tagNames.size(); i++) {
            List<Long> currentTagImageIds = imageTagRepository.findImageIdsByTagName(tagNames.get(i));
            imageIds.retainAll(currentTagImageIds);
        }

        List<Image> images = imageRepository.findAllById(imageIds)
                .stream()
                .filter(image -> !image.getIsDeleted())
                .collect(Collectors.toList());

        return images.stream().map(this::convertToDTO).collect(Collectors.toList());
    }

    /**
     * 根据MIME类型获取图片
     */
    public List<ImageDTO> getImagesByMimeType(String mimeType) {
        log.info("Getting images by MIME type: {}", mimeType);

        List<Image> images = imageRepository.findByMimeTypeAndIsDeletedFalse(mimeType);
        return images.stream().map(this::convertToDTO).collect(Collectors.toList());
    }

    /**
     * 根据时间范围获取图片
     */
    public List<ImageDTO> getImagesByDateRange(LocalDateTime startTime, LocalDateTime endTime) {
        log.info("Getting images by date range: {} to {}", startTime, endTime);

        List<Image> images = imageRepository.findByIsDeletedFalseAndCreatedAtBetween(startTime, endTime);
        return images.stream().map(this::convertToDTO).collect(Collectors.toList());
    }

    /**
     * 获取热门图片（按使用次数排序）
     */
    public Page<ImageDTO> getPopularImages(int page, int size) {
        log.info("Getting popular images: page={}, size={}", page, size);

        Pageable pageable = PageRequest.of(page, size);
        Page<Image> imagePage = imageRepository.findByIsDeletedFalseOrderByUsageCountDesc(pageable);
        return imagePage.map(this::convertToDTO);
    }

    /**
     * 按使用次数排序获取图片
     */
    public Page<ImageDTO> getImagesSortedByUsage(int page, int size, String sortDir) {
        log.info("Getting images sorted by usage: page={}, size={}, sortDir={}", page, size, sortDir);

        Sort sort = Sort.by(Sort.Direction.fromString(sortDir), "usageCount");
        Pageable pageable = PageRequest.of(page, size, sort);

        Page<Image> imagePage = imageRepository.findByIsDeletedFalse(pageable);
        return imagePage.map(this::convertToDTO);
    }

    /**
     * 按时间排序获取图片
     */
    public Page<ImageDTO> getImagesSortedByTime(int page, int size, String timeField, String sortDir) {
        log.info("Getting images sorted by time: page={}, size={}, timeField={}, sortDir={}", page, size, timeField, sortDir);

        // 验证时间字段参数
        if (!timeField.equals("createdAt") && !timeField.equals("updatedAt")) {
            throw new IllegalArgumentException("时间字段只能是 createdAt 或 updatedAt");
        }

        Sort sort = Sort.by(Sort.Direction.fromString(sortDir), timeField);
        Pageable pageable = PageRequest.of(page, size, sort);

        Page<Image> imagePage = imageRepository.findByIsDeletedFalse(pageable);
        return imagePage.map(this::convertToDTO);
    }

    /**
     * 更新图片信息
     */
    @Transactional
    public ImageDTO updateImage(Long id, ImageDTO imageDTO) {
        log.info("Updating image: {}", id);

        Image image = imageRepository.findByIdAndIsDeletedFalse(id)
                .orElseThrow(() -> new IllegalArgumentException("图片不存在或已删除"));

        // 更新基本信息
        if (imageDTO.getName() != null) {
            image.setName(imageDTO.getName());
        }
        if (imageDTO.getDescription() != null) {
            image.setDescription(imageDTO.getDescription());
        }

        // 更新标签
        if (imageDTO.getTags() != null) {
            updateImageTags(image, imageDTO.getTags());
        }

        Image savedImage = imageRepository.save(image);
        return convertToDTO(savedImage);
    }

    /**
     * 增加图片使用次数
     */
    @Transactional
    public void incrementUsageCount(Long id) {
        log.info("Incrementing usage count for image: {}", id);
        imageRepository.incrementUsageCount(id);
    }

    /**
     * 软删除图片
     */
    @Transactional
    public void deleteImage(Long id) {
        log.info("Soft deleting image: {}", id);

        Image image = imageRepository.findByIdAndIsDeletedFalse(id)
                .orElseThrow(() -> new IllegalArgumentException("图片不存在或已删除"));

        imageRepository.softDeleteById(id);
    }

    /**
     * 批量删除图片
     */
    @Transactional
    public void deleteImages(List<Long> ids) {
        log.info("Batch deleting images: {}", ids);
        imageRepository.softDeleteByIds(ids);
    }

    /**
     * 获取图片统计信息
     */
    public ImageStatistics getImageStatistics() {
        log.info("Getting image statistics");

        long totalImages = imageRepository.countByIsDeletedFalse();
        long jpegCount = imageRepository.countByMimeTypeAndIsDeletedFalse("image/jpeg");
        long pngCount = imageRepository.countByMimeTypeAndIsDeletedFalse("image/png");
        long gifCount = imageRepository.countByMimeTypeAndIsDeletedFalse("image/gif");
        long webpCount = imageRepository.countByMimeTypeAndIsDeletedFalse("image/webp");

        ImageStatistics stats = new ImageStatistics();
        stats.setTotalImages(totalImages);
        stats.setJpegCount(jpegCount);
        stats.setPngCount(pngCount);
        stats.setGifCount(gifCount);
        stats.setWebpCount(webpCount);

        return stats;
    }

    /**
     * 获取热门标签
     */
    public List<TagStatistics> getPopularTags(int limit) {
        log.info("Getting popular tags with limit: {}", limit);

        List<Object[]> results = imageRepository.findPopularTags(limit);
        return results.stream()
                .map(result -> {
                    TagStatistics stats = new TagStatistics();
                    stats.setTagName((String) result[0]);
                    stats.setUsageCount(((Number) result[1]).longValue());
                    return stats;
                })
                .collect(Collectors.toList());
    }

    /**
     * 更新图片标签
     */
    private void updateImageTags(Image image, List<String> tagNames) {
        // 删除现有标签关联
        imageTagRepository.deleteByImageId(image.getId());

        // 添加新标签关联
        for (String tagName : tagNames) {
            Tag tag = tagRepository.findByNameAndIsDeletedFalse(tagName)
                    .orElseGet(() -> {
                        Tag newTag = new Tag();
                        newTag.setName(tagName);
                        newTag.setCategory("manual");
                        newTag.setUsageCount(0);
                        newTag.setIsDeleted(false);
                        return tagRepository.save(newTag);
                    });

            ImageTag imageTag = new ImageTag();
            imageTag.setImage(image);
            imageTag.setTag(tag);
            imageTag.setSource(ImageTag.TagSource.MANUAL);
            imageTagRepository.save(imageTag);
        }

        // 更新图片的tags字段
        image.setTags(String.join(",", tagNames));
    }

    /**
     * 转换为DTO
     */
    private ImageDTO convertToDTO(Image image) {
        ImageDTO dto = new ImageDTO();
        dto.setId(image.getId());
        dto.setName(image.getName());
        dto.setOriginalName(image.getOriginalName());
        dto.setFileUrl(image.getFileUrl());
        dto.setFileSize(image.getFileSize());
        dto.setMimeType(image.getMimeType());
        dto.setWidth(image.getWidth());
        dto.setHeight(image.getHeight());
        dto.setDescription(image.getDescription());
        dto.setAiRecognitionStatus(image.getAiRecognitionStatus());
        dto.setCreatedAt(image.getCreatedAt());
        dto.setUpdatedAt(image.getUpdatedAt());
        dto.setUsageCount(image.getUsageCount());

        // 获取标签
        List<String> tagNames = imageTagRepository.findTagNamesByImageId(image.getId());
        dto.setTags(tagNames);

        // 统计相关内容数量
        long textContentCount = textContentRepository.countByImageIdAndIsDeletedFalse(image.getId());
        dto.setTextContentCount((int) textContentCount);

        long generatedImageCount = generatedImageRepository.countByOriginalImageIdAndIsDeletedFalse(image.getId());
        dto.setGeneratedImageCount((int) generatedImageCount);

        return dto;
    }

    /**
     * 图片统计信息
     */
    public static class ImageStatistics {
        private long totalImages;
        private long jpegCount;
        private long pngCount;
        private long gifCount;
        private long webpCount;

        // Getters and Setters
        public long getTotalImages() { return totalImages; }
        public void setTotalImages(long totalImages) { this.totalImages = totalImages; }

        public long getJpegCount() { return jpegCount; }
        public void setJpegCount(long jpegCount) { this.jpegCount = jpegCount; }

        public long getPngCount() { return pngCount; }
        public void setPngCount(long pngCount) { this.pngCount = pngCount; }

        public long getGifCount() { return gifCount; }
        public void setGifCount(long gifCount) { this.gifCount = gifCount; }

        public long getWebpCount() { return webpCount; }
        public void setWebpCount(long webpCount) { this.webpCount = webpCount; }
    }

    /**
     * 标签统计信息
     */
    public static class TagStatistics {
        private String tagName;
        private long usageCount;

        // Getters and Setters
        public String getTagName() { return tagName; }
        public void setTagName(String tagName) { this.tagName = tagName; }

        public long getUsageCount() { return usageCount; }
        public void setUsageCount(long usageCount) { this.usageCount = usageCount; }
    }

    /**
     * 根据用户ID获取图片（分页）
     * @author wangguiyou
     * @param userId 用户ID
     * @param page 页码
     * @param size 每页大小
     * @param sortBy 排序字段
     * @param sortDir 排序方向
     * @return 分页图片列表
     */
    public Page<ImageDTO> getImagesByUserId(Long userId, int page, int size, String sortBy, String sortDir) {
        log.info("Getting images by user ID: {}, page={}, size={}, sortBy={}, sortDir={}", userId, page, size, sortBy, sortDir);

        Sort sort = Sort.by(Sort.Direction.fromString(sortDir), sortBy);
        Pageable pageable = PageRequest.of(page, size, sort);

        Page<Image> imagePage = imageRepository.findByUserIdAndIsDeletedFalse(userId, pageable);
        return imagePage.map(this::convertToDTO);
    }

}
